package com.course.gateway.filter;

import com.course.gateway.component.HandleException;
import com.course.gateway.config.IgnoreUrlsConfig;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * @PROJECT_NAME: course
 * @DESCRIPTION: 网关全局过滤器
 * @Author: 涂玄武
 * @DATE: 2021/6/24 9:59
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(LoginAdminGatewayFilter.class);

    //白名单列表（黑名单）
    @Resource
    private IgnoreUrlsConfig ignoreUrlsConfig;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private HandleException handleException;
    //网关端口号
    @Value("server.port")
    private String serverPort;

    /**
     * 身份校验处理
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.判断当前请求是否在白名单中
        AntPathMatcher pathMatcher = new AntPathMatcher();
        boolean flag = false;
        //获取请求的路径
        String path = exchange.getRequest().getURI().getPath();
        for (String url : ignoreUrlsConfig.getUrls()) {
            if (pathMatcher.match(url, path)) {
                flag = true;
                break;
            }
        }

        //白名单放行
        if (flag) {
            return chain.filter(exchange);
        }

        //2.获取access_token
        String accessToken = exchange.getRequest().getQueryParams().getFirst("access_token");
        //判断access_token是否为空
        if (StringUtils.isBlank(accessToken)) {
            return handleException.writeError(exchange, "请登录!");
        }
        //3.校验token是否有效
        String checkTokenUrl = "http://oauth2-server/oauth/check_token?token=".concat(accessToken);
        //发送远程请求，验证token-逻辑异常返回处理
        try {
            ResponseEntity<String> entity = restTemplate.getForEntity(checkTokenUrl, String.class);
            logger.info("发送远程请求，验证token：{}",entity);
            //处理token无效的业务逻辑处理
            if (entity.getStatusCode() != HttpStatus.OK) {
                return handleException.writeError(exchange,
                        "toke已过期,token:".concat(accessToken));
            }
            if (StringUtils.isBlank(entity.getBody())) {
                return handleException.writeError(exchange, "非法token,token:".concat(accessToken));
            }
        } catch (Exception e) {
            return handleException.writeError(exchange,
                    "toke已过期,token:".concat(accessToken));
        }
        //放行token验证成功的token时，放入当前网关的端口号
        //搭建Gateway集群时用于区分服务接收请求时的来源网关
        ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().header("serverPort",serverPort).build();
        return chain.filter(exchange.mutate().request(serverHttpRequest).build());
    }

    /**
     * 网关过滤器的排序，数字越小优先级越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 2;
    }
}
